//
// Created by djy on 2019/7/23.
//
#include <string.h>
#include <stdio.h>

#include "../inc/setting.h"
#include "../inc/virtual_flash.h"
#include "../inc/comfun.h"

setting_t setting;
static uint32_t setting_start_addr = SETTING_INVALID_ADDR;

static void board_feed_wdg()
{

}

void dev_show(void)
{
    static char str[34];

    printf("AID: %s\n", arr2str(setting.encode.id, sizeof(setting.encode.id), str, sizeof(str)));
    printf("PWD: %s\n", arr2str(setting.encode.pwd, sizeof(setting.encode.pwd), str, sizeof(str)));
    printf("SN: %s\n",  arr2str(setting.encode.sn, sizeof(setting.encode.sn), str, sizeof(str)));
    printf("DKey: %s\n", arr2str(setting.encode.dkey, sizeof(setting.encode.dkey), str, sizeof(str)));
    printf("PID: %s\n", arr2str(setting.para.panid, sizeof(setting.para.panid), str, sizeof(str)));
    printf("GID: %s\n", arr2str(setting.para.gid, sizeof(setting.para.gid), str, sizeof(str)));
    printf("SID: %s\n", arr2str(setting.para.sid, sizeof(setting.para.sid), str, sizeof(str)));
    //printf("TEST:%s\n", arr2str(setting.test, sizeof(setting.test),str, sizeof(str)));
    printf("-------------------------------------------\n\n");
}


static void setting_default()
{
    memset(&setting, 0, sizeof(setting));

    uint8_t sn[]= {0x31,0x72,0x11,0x00,0x00,0x51,0x92,0x61,0x99,0x00,0x00,0x01};
    uint8_t dk[]= {0x30,0x30,0x30,0x30,0X39,0x50,0x41,0x52};
    put_le_val(709284, setting.encode.id, 4);
    put_le_val(50674, setting.encode.pwd, 2);
    memcpy(setting.encode.sn, sn, sizeof(sn));
    memcpy(setting.encode.dkey, dk, sizeof(dk));

}

void setting_save(void)
{
    setting_hdr_t hdr;
    uint32_t addr = setting_start_addr + sizeof(setting_t);//起始地址+当前使用的数据长度
    BOOL new_sec = FALSE;

    //如果addr大于存储空间
    if (addr >= SETTING_FROM + SETTING_SIZE || (addr + sizeof(setting_t) >= SETTING_FROM + SETTING_SIZE))
    {
        addr = SETTING_FROM; //存储地址切换到最开始
        new_sec = TRUE;      //更新重新存储标志
    }
    //如果即将使用的存储空间超过一页
    if ((addr & FLASH_SECTOR_MASK) + sizeof(setting_t) > FLASH_SECTOR_SIZE)
    {
        addr = (addr + FLASH_SECTOR_SIZE) & (~FLASH_SECTOR_MASK);//从下一页开始
        new_sec = TRUE;
    }
    //首次使用
    if (!(addr & FLASH_SECTOR_MASK))
    {
        new_sec = TRUE;
    }

    /* erase next sector if need a new sector */
    if (new_sec)
    {
        flash_erase(addr,FLASH_SECTOR_SIZE);
    }

    /* check memory */
    setting_t tmp;
    flash_read((uint8_t *)&tmp, addr, sizeof(tmp));
    if(!is_all_xx((uint8_t *)&tmp, 0xFF, sizeof(tmp)))
    {
        printf("err occur\n");
        return ;
    }

    //save setting data
    if(!flash_write(setting_data_addr(setting),addr + sizeof(setting_hdr_t),SETTING_DAT_SIZE))
        printf("flash write err\n");

    hdr.crc = add_crc16(setting_data_addr(setting), SETTING_DAT_SIZE);
    hdr.magic = SETTING_MAGIC;
    flash_write((uint8_t *)&hdr,addr,sizeof(hdr));//save setting crc &magic

    if (setting_start_addr < SETTING_FROM + SETTING_SIZE)
    {
        memset(&hdr, 0, sizeof(hdr));
        flash_write((uint8_t *)&hdr,setting_start_addr,sizeof(hdr));//change last setting crc &magic
    }

    setting_start_addr = addr;
    printf("setting_start_addr is  0x%06X!\r\n", addr);
}

void setting_load(void)
{
    setting_hdr_t hdr;
    uint32_t addr = SETTING_FROM;

    //  参数存储起始地址            是否超出范围                       步长：参数存储大小
    for (addr = SETTING_FROM; addr < SETTING_FROM + SETTING_SIZE; addr += sizeof(setting_t))
    {
        //将要读取的flash地址超过一整页
        if ((addr & FLASH_SECTOR_MASK) + sizeof(setting_t) > FLASH_SECTOR_SIZE)
        {
            addr = (addr + FLASH_SECTOR_SIZE) & (~FLASH_SECTOR_MASK); //从下一页开始
        }

        if(addr >= SETTING_FROM + SETTING_SIZE)//下一页超出寻址范围
        {
            break;
        }
        board_feed_wdg();//读取flash时间长 防止看门狗复位

        //读取hdr  校验 magic
        flash_read((uint8_t*)&hdr,addr, SETTING_HDR_SIZE);
        if (hdr.magic != SETTING_MAGIC) continue;//如果存储标志不一样  继续循环

        //读取剩余数据  校验CRC
        flash_read(setting_data_addr(setting),addr + SETTING_HDR_SIZE,SETTING_DAT_SIZE);
        if (hdr.crc != add_crc16(setting_data_addr(setting), SETTING_DAT_SIZE)) continue;//crc校验不过  继续循环

        //找到正确数据
        setting_start_addr = addr;
        printf("setting_load here has data addr: 0x%06X!\r\n", addr);
        return;
    }

    printf("setting default\n\n");
    setting_default();//未找到正确数据  默认部分参数
    setting_save();//参数保存
}
